package com.daxia.bumall.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.daxia.bumall.common.AuditStatus;
import com.daxia.bumall.common.RoleCode;
import com.daxia.bumall.common.SmsSendType;
import com.daxia.bumall.common.UserType;
import com.daxia.bumall.dao.CompanyDAO;
import com.daxia.bumall.dao.DesignCollectionDAO;
import com.daxia.bumall.dao.DesignDAO;
import com.daxia.bumall.dao.DesignerDAO;
import com.daxia.bumall.dao.DesignerFanDAO;
import com.daxia.bumall.dao.OrderDAO;
import com.daxia.bumall.dao.TimelineDAO;
import com.daxia.bumall.dao.UserDAO;
import com.daxia.bumall.dto.CompanyDTO;
import com.daxia.bumall.dto.DesignerDTO;
import com.daxia.bumall.dto.OPResultDTO;
import com.daxia.bumall.dto.UserDTO;
import com.daxia.bumall.exception.BizException;
import com.daxia.bumall.model.City;
import com.daxia.bumall.model.Company;
import com.daxia.bumall.model.Designer;
import com.daxia.bumall.model.DesignerFan;
import com.daxia.bumall.model.User;
import com.daxia.bumall.security.PasswordEncoder;
import com.daxia.bumall.support.Page;
import com.daxia.bumall.util.BeanMapper;
import com.daxia.bumall.util.SmsService;
import com.daxia.bumall.util.SpringSecurityUtils;
import com.daxia.bumall.util.ValidationUtils;

@Service
public class UserService extends BaseService {
	@Autowired
	private UserRoleService userRoleService;
	
	@Autowired
	private PasswordEncoder passwordEncoder;
	
	@Autowired
	private UserDAO userDAO;

	@Autowired
	private TimelineDAO timelineDAO;

	@Autowired
	private OrderDAO orderDAO;

	@Autowired
	private DesignDAO designDAO;

    @Autowired
    private DesignerFanDAO designerFanDAO;

	@Autowired
	private DesignCollectionDAO designCollectionDAO;
	
	@Autowired
	private CompanyDAO companyDAO;
	@Autowired
	private CompanyService companyService;
	@Autowired
	private DesignerDAO designerDAO;
	
	public List<UserDTO> find(UserDTO query, Page page) {
		List<User> models = userDAO.find(query, page);
		List<UserDTO> dtos = toDTOs(models);
		return dtos;
	}
	
	public List<UserDTO> findAll() {
		return this.find(new UserDTO(), null);
	}
	
	public List<UserDTO> find(int count) {
		Page page = new Page();
		page.setPage(1);
		page.setPageSize(count);
		return this.find(new UserDTO(), page);
	}
	
	public Long create(UserDTO dto) {
		User model = new User();
		toModel(model, dto);
		ValidationUtils.assertTrue(model.getType() != null, "用户类型不能为空");
		if (model.getType() == UserType.City.getValue()) { // 一个城市只能有一个城市运营商
			ValidationUtils.assertTrue(model.getCity() != null && model.getCity().getId() != null, "城市不能为空");
			int count = userDAO.countByTypeAndCity(UserType.City.getValue(), model.getCity().getId());
			if (count > 0) {
				error("该城市已经有运营商了");
			}
		}
		Long id = userDAO.create(model);
		
		if (model.getType() == UserType.Manager.getValue()) {
			userRoleService.addRole(RoleCode.OgAdmin, id);
		} if (model.getType() == UserType.City.getValue()) {
			userRoleService.addRole(RoleCode.City, id);
		} else if (model.getType() == UserType.DecorateCompany.getValue()) {
			userRoleService.addRole(RoleCode.Company, id);
		} else if (model.getType() == UserType.Designer.getValue()) {
			userRoleService.addRole(RoleCode.Designer, id);
		} else if (model.getType() == UserType.Factory.getValue()) {
			userRoleService.addRole(RoleCode.Factory, id);
		}
		
		return id;
	}
	
	public UserDTO load(Long id) {
	    User model = userDAO.load(id);
	    return toDTO(model);
    }

	public void updateAllFields(UserDTO dto) {
		User model = userDAO.load(dto.getId());
		if (model.getType() != dto.getType()) {
			throw new RuntimeException("禁止修改用户类型");
		}
		toModel(model, dto);
		userDAO.update(model);
    }
	
	public void updateSeedStatus(UserDTO dto) {
		User old = userDAO.load(dto.getId());
		old.setSeedStatus(dto.getSeedStatus());
		userDAO.update(old);
	}

	public void deleteByIds(Long[] ids) {
		if (ids != null) {
			for (Long id : ids) {
				if (id == 1) {
					throw new RuntimeException("该用户无法删除");
				}
				userDAO.deleteById(id);
			}
		}
    }
	
	public void deleteById(Long id) {
		this.deleteByIds(new Long[] {id});
	}
	
	public UserDTO findOne(UserDTO query) {
		User model = userDAO.findOne(query);
		return toDTO(model);
	}
	
	private List<UserDTO> toDTOs(List<User> models) {
		if (CollectionUtils.isEmpty(models)) {
			return new ArrayList<UserDTO>(0);
		}
		List<UserDTO> dtos = new ArrayList<UserDTO>(models.size());
		for (User model : models) {
	        UserDTO dto = toDTO(model);
	        dtos.add(dto);
        }
	    return dtos;
    }
    
    private UserDTO toDTO(User model) {
		if (model == null) {
			return null;
		}
		UserDTO dto = BeanMapper.map(model, UserDTO.class);
		
		return dto;
	}
	
	private void toModel(User model, UserDTO dto) {
		BeanMapper.copy(dto, model);
    }
	
	@SuppressWarnings("unused")
	private List<User> toModels(List<UserDTO> dtos) {
		if (CollectionUtils.isEmpty(dtos)) {
			return new ArrayList<User>(0);
		}
		List<User> models = new ArrayList<User>(dtos.size());
		for (UserDTO dto : dtos) {
	        User model = new User();
	        toModel(model, dto);
	        models.add(model);
        }
		return models;
	}
	public UserDTO findByOpenid(String openid) {
        UserDTO query = new UserDTO();
        query.setOpenid(openid);
        return this.findOne(query);
    }

    /**
     * 如果nickname已经存在了，就生成一个随机字符
     * @param nickName
     * @return
     */
    public String confirmNickName(String nickName) {
        int idx = 1;
        String tmpNickName = nickName;
        while (true) {
            UserDTO query = new UserDTO();
            query.setNickName(tmpNickName);
            User user = userDAO.findOne(query);
            if (user == null) {
                return tmpNickName;
            } else {
                tmpNickName = nickName + (idx ++);
            }
        }        
                
    }

    
    public List<UserDTO> findByParentUser(Long parentUserId) {
    	/*
        UserDTO query = new UserDTO();
        query.setParentUser(new User());
        query.getParentUser().setId(parentUserId);
        return this.find(query, null); */
    	return null;
    }
 
    @Transactional
    public void updateLocation(Long id, Double latitude, Double longitude) {
        User u = userDAO.load(id);
        u.setLatitude(latitude);
        u.setLongitude(longitude);
        u.setLastGpsUpdatedTime(new Date());
        userDAO.update(u);
    }
    
    public boolean isMobileRegistered(String mobile) {
        UserDTO dto = new UserDTO();
        dto.setMobile(mobile);
        User user = userDAO.findOne(dto);
        UserDTO findUser = toDTO(user);
        return findUser != null;
    }
    
    @Transactional
	public Long registerForMobile(String mobile, String inviteCode, String client, String password) {
	    Date now = new Date();
	    User user = new User();
	    user.setMobile(mobile);
	    user.setUsername(mobile);
	    user.setPassword(passwordEncoder.encodePassword(password, mobile));
	    user.setType(UserType.Normal.getValue());
	    user.setCreatetime(now);
	    Long id = userDAO.create(user);

	    user = userDAO.load(id);
        userDAO.update(user);
	    
	    return id;
    }
    
    public UserDTO login(String username, String password) {
		ValidationUtils.assertTrue(StringUtils.isNotBlank(username), "用户名不能为空");
		ValidationUtils.assertTrue(StringUtils.isNotBlank(password), "密码不能为空");
		
		UserDTO query = new UserDTO();
		query.setUsername(username);
		query.setPassword(passwordEncoder.encodePassword(password, username));
		
		User user = userDAO.findOne(query);
		if (user == null || !username.equalsIgnoreCase(user.getUsername())) {
			return null;
		} 
		return toDTO(user);
    }

	/**
	 * 统计用户的 动态数、 订单数、 作品数（Design) 和 收藏数(DesignCollection)
	 * @param user
	 */
	public void count(UserDTO user) {

		int timelineNum = timelineDAO.count(user.getId());
		user.setTimelineNum(timelineNum);

		int orderNum = orderDAO.count(user.getId());
		user.setOrderNum(orderNum);

		int designNum = designDAO.count(user.getId());
		user.setDesignNum(designNum);

		int designCollectionNum = designCollectionDAO.count(user.getId());
		user.setDesignCollectionNum(designCollectionNum);
	}

	/**
	 *  重置密码
	 *
	 * @param mobile  手机号码
	 * @param password 新密码
	 * @param client client值
	 * @return
	 */
	@Transactional
	public OPResultDTO resetPassword(String mobile, String password, String client) {
		if ( !isMobileRegistered(mobile)) {
			throw new BizException("手机号码未注册");
		}

		User user = userDAO.findUserByMobile(mobile);
		if ( user == null ){
			throw new BizException("手机号码未注册");
		}

		user.setPassword(passwordEncoder.encodePassword(password, mobile));
		userDAO.update(user);

		return new OPResultDTO(200, "success");
	}

    /**
     *  获取用户的粉丝列表
     *
     * @param mobile  设计师手机号码
     * @param client
     * @param page
     * @return
     */
    public List<UserDTO> loadMyFans(String mobile, String client, Page page) {

        User user = userDAO.findUserByMobile(mobile);
        if ( user == null ){
            throw new BizException("手机号码未注册");
        }

        List<DesignerFan> designerFanList = designerFanDAO.findByDesignerUserId(user.getId(), page);
        if (CollectionUtils.isEmpty(designerFanList)){
            return Collections.EMPTY_LIST;
        }

        List<User> fans = new ArrayList<User>();
        for (DesignerFan designerFan : designerFanList) {
            fans.add(designerFan.getFan());
        }

        return toDTOs(fans);
    }

    public List<UserDTO> loadMyDesigners(String mobile, String client, Page page) {
        User user = userDAO.findUserByMobile(mobile);
        if ( user == null ){
            throw new BizException("手机号码未注册");
        }

        List<DesignerFan> designerFanList = designerFanDAO.findByFanUserId(user.getId(), page);
        if (CollectionUtils.isEmpty(designerFanList)){
            return Collections.EMPTY_LIST;
        }

        List<User> designers = new ArrayList<User>();
        for (DesignerFan designerFan : designerFanList) {
            designers.add(designerFan.getDesigner());
        }

        return toDTOs(designers);
    }

    @Transactional
	public void resetPassword(String newPassword, Long userId) {
		User user = userDAO.load(userId);
		if ( user == null ){
			throw new BizException("该用户不存在");
		}
		String newPwd = passwordEncoder.encodePassword(newPassword, user.getUsername());
		user.setPassword(newPwd);
		userDAO.update(user);
	}
    
    public UserDTO findByMobile(String mobile) {
    	User user = userDAO.findUserByMobile(mobile);
    	return toDTO(user);
    }

    
    @Transactional
    public CompanyDTO companySave(CompanyDTO companyDTO) {
    	ValidationUtils.assertTrue(StringUtils.isNotBlank(companyDTO.getMobile()), "请输入手机号码");
    	CompanyDTO company = new CompanyDTO();
    	BeanMapper.copy(companyDTO, company);
    	
    	CompanyDTO query = new CompanyDTO();
    	query.setName(companyDTO.getName());
    	Company temp = companyDAO.findOne(query);
    	CompanyDTO dto = new CompanyDTO();
    	if (null != temp) {
    		/*company.setId(temp.getId());
    		companyDAO.update(company);
    		dto = BeanMapper.map(company, CompanyDTO.class);*/
    		
    	} else {
    		User user = new User();
        	user.setUsername(company.getMobile());
        	user.setPassword(passwordEncoder.encodePassword("123456", user.getUsername()));
        	
        	user.setType(UserType.DecorateCompany.getValue());//
        	user.setProvince(companyDTO.getProvince());
        	user.setCity(companyDTO.getCity());
        	user.setDistrict(companyDTO.getDistrict());
        	
        	Long id = userDAO.create(user);
        	
        	userRoleService.addRole(RoleCode.Company, id);
        	
        	user.setId(id);
        	
        	company.setUser(user);
        	companyService.create(company);
        	dto = BeanMapper.map(company, CompanyDTO.class);
        	dto.setUser(user);
    	}
    	return dto;
    }
    
    @Transactional
    public void designerSave(DesignerDTO designerDTO, String mobile) throws Exception {
    	ValidationUtils.assertTrue(StringUtils.isNotBlank(mobile), "请输入手机号码");
    	Designer designer = new Designer();
    	BeanMapper.copy(designerDTO, designer);
    	
    	if (designerDTO.getId() != null) {
    		User user = userDAO.load(designerDTO.getUser().getId());
    		user.setRealName(designerDTO.getUser().getRealName());
    		user.setNickName(designerDTO.getUser().getNickName());
    		user.setMobile(mobile);
    		user.setProvince(designerDTO.getProvince());
    		user.setCity(designerDTO.getCity());
    		user.setDistrict(designerDTO.getDistrict());
    		if (user.getType() != UserType.DecorateCompany.getValue()) { 
    			// 不是装修公司的话，可以修改是否推荐
    		}
    		System.out.println("hello");
    		userDAO.update(user);
    		
    		Designer d = designerDAO.load(designerDTO.getId());
    		BeanMapper.copy(designerDTO, d);
    		designerDAO.update(d);
    	} else {
    		User user = designerDTO.getUser();
    		user.setUsername(mobile);
    		
    		user.setRealName(designerDTO.getUser().getRealName());
    		user.setNickName(designerDTO.getUser().getNickName());
    			user.setPassword(passwordEncoder.encodePassword("123456", mobile));
    		user.setProvince(designerDTO.getProvince());
    		user.setCity(designerDTO.getCity());
    		user.setDistrict(designerDTO.getDistrict());
        	user.setType(UserType.Designer.getValue());
        	
        	
        	Long id = userDAO.create(user);
        	
        	userRoleService.addRole(RoleCode.Designer, id);
        	
        	user.setId(id);
        	
        	designer.setUser(user);
        	
        	User current = (User) SpringSecurityUtils.getCurrentUser();
        	//if (current.getType() == UserType.Manager.getValue()) {
        		designer.setAuditStatus(AuditStatus.Success.getValue());
        		designer.setAuditTime(new Date());
        		designer.setAuditUser(current);
        		designer.setAuditRemark(AuditStatus.Success.getRemark());
        		SmsService.sendWithTemplate(designerDTO.getUser().getMobile(), SmsSendType.DesignerAudited.getValue(), new HashMap<String, Object>());
        	//}
        	designerDAO.create(designer);
    	}
    }
     
    /**
     * 查找用户的子帐号（装修公司和设计师)
     * @param userId
     * @param page
     * @return
     */
    public List<UserDTO> findSubAccounts(Long userId, Page page) {
    	User parent = userDAO.load(userId);
    	UserDTO query = new UserDTO();
    	query.setCity(parent.getCity());
    	query.setQuerySubacount(true);
    	return this.find(query, page);
    }
    
    /**
     * 查找用户的子帐号（只装修公司）
     * @param userId
     * @return
     */
    public List<UserDTO> findSubAccountsOfCompany(Long userId, Page page) {
    	return null;
    }
    /**
     * 查找seq
     */
    /*
    public string findSeq(UserDTO dto) {
    	User user = userDAO.findSeq(dto);
    	if (user == null) {
    		return 0;
    	}
    	return user.getSeq();
    }*/

    /**
     * 根据城市查找运营商
     * @param id
     * @return
     */
	public UserDTO findCityOperatorByCity(Long id) {
		UserDTO query = new UserDTO();
		query.setCity(new City());
		query.getCity().setId(id);
		query.setType(UserType.City.getValue());
		List<User> models = userDAO.find(query, null);
		if (models.size() > 1) {
			throw new RuntimeException(models.get(0).getCity().getName() + "有" + models.size() + "位运营商，请检查");
		}
		if (CollectionUtils.isEmpty(models)) {
			UserDTO user = this.findByUsername("ogadmin");
			return user;
		} else {
			return toDTO(models.get(0));
		}
	}

	public UserDTO findByUsername(String username) {
		UserDTO query = new UserDTO();
		query.setUsername(username);
		return toDTO(userDAO.findOne(query));
	}

	public List<UserDTO> findByType(UserType userType) {
		UserDTO query = new UserDTO();
		query.setType(userType.getValue());
		return this.find(query, null);
	}

	public int countSubAccounts(Long parentUserId, Date startDate, Date endDate) {
		return userDAO.countSubAccounts(parentUserId, startDate, endDate);
	}
    /**
     * 更新最后登录时间
     * @param userId
     */
	public void updateLastLoginTime(Long userId){
		UserDTO dto=new UserDTO();
		dto.setId(userId);
		dto.setLastLoginTime(new Date());
		userDAO.updateLastLoginTime(dto);
	}
	public UserDTO findByOgSessionId(String ogSessionId) {
		if (StringUtils.isBlank(ogSessionId)) {
			return null;
		}
		UserDTO query = new UserDTO();
		query.setOgSessionId(ogSessionId);
		return this.findOne(query);
	}
	
	/**
	 * 如果没有找到就会创建
	 * @param userId
	 * @return
	 */
	@Transactional
	public String getOgSessionId(Long userId) {
		User user = userDAO.load(userId);
		if (StringUtils.isNotBlank(user.getOgSessionId())) {
			return user.getOgSessionId();
		}
		String ogSessionId = UUID.randomUUID().toString();
		user.setOgSessionId(ogSessionId);
		userDAO.update(user);
		return ogSessionId;
	}
}
